﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace WindowsGame1
{
    class Streamline
    {
        /// <summary>
        /// Points of Streamline
        /// </summary>
        protected List<List<Vector2>> _lineVectors;
        /// <summary>
        /// Data of Vectorfield
        /// </summary>
        // protected DataVector[, ,] _dataVectors;
        /// <summary>
        /// Vectorfield
        /// </summary>
        protected Vectorfield _vectorfield;

        /// <summary>
        /// Constructor for Streamline
        /// </summary>
        /// <param name="dataVectors">field of dataVectors</param>
        //  public Streamline(DataVector[, ,] dataVectors )
        public Streamline(Vectorfield vectorfield)
        {
            _lineVectors = new List<List<Vector2>>();
            _vectorfield = vectorfield;

        }

        public List<List<Vector2>> lineVectors
        {
            get
            {
                return _lineVectors;
            }
        }




        /// <summary>
        /// Calculate Streamline from startvector until a given stoplength
        /// </summary>
        /// <param name="startpos">startpos of streamline in Vectorfield coordinates</param>
        /// <param name="stopLenght">stopLength of streamline in Vectorfield coordinates</param>
        public void Calculate(List<Vector2> startpos, float stopLength)
        {
            _lineVectors = new List<List<Vector2>>();

            foreach (Vector2 startpoint in startpos)
            {
                float currentLength = 0;
                Vector2 last;
                Vector2 position1;
                Vector2 position2;
                Vector2 grad11;
                Vector2 grad21;
                Vector2 grad12;
                Vector2 grad22;
                Vector2 interpolatedDirection;

                List<Vector2> streamline = new List<Vector2>();

                streamline.Add(startpoint);
                while (currentLength < stopLength)
                {
                    last = streamline.Last();
                    interpolatedDirection = _vectorfield.BilinearInterpolateDirection(last, true);
                    ////Interpolation: Get the Neighborhood and calculate gradients
                    //position1 = last;
                    //position2 = last + Vector2.One;
                    
                    //grad11 = _vectorfield.getDataVectorAt(position1).direction;
                    //grad21 = _vectorfield.getDataVectorAt(new Vector2(position2.X, position2.Y)).direction;
                    //grad12 = _vectorfield.getDataVectorAt(new Vector2(position1.X, position2.Y)).direction;
                    //grad22 = _vectorfield.getDataVectorAt(position2).direction;
                    ////bilinear interpolation
                    //Vector2 interpolatedDirection = bilinear_interpolation(position1.X, position2.X, position1.Y, position2.Y, grad11, grad21, grad12, grad22, last);
                    //Calculate Length of the streamline
                    if (interpolatedDirection.Length() == 0)
                    {
                        break;
                    }
                    Vector2 nextPoint;

                    if (currentLength + interpolatedDirection.Length() >= stopLength)
                    {
                        float rest = stopLength - currentLength;
                        float ratio = interpolatedDirection.Length() / rest;
                        nextPoint = last + 0.05f * interpolatedDirection/ratio;
                    }
                    else
                    {
                        //0.05f*interpol = stepwidth
                        nextPoint = last + 0.05f * interpolatedDirection;
                    }
                    //check if a point is drawn outside of the immage
                    //FIXME: add constants / real widht /height
                    if (nextPoint.X > 800 - 1 || nextPoint.X < 0 || nextPoint.Y > 600 - 1 || nextPoint.Y < 0)
                    {
                        break;
                    }
                    
                    else
                    {
                        //add vector to streamline and calculate new length
                        streamline.Add(nextPoint);

                        currentLength += interpolatedDirection.Length();

                    }
                }

                _lineVectors.Add(streamline);

            }

        }
        


        /// <summary>
        /// Draw Streamline
        /// </summary>
        public void Draw(SpriteBatch batch, GraphicsDevice currentGraphicsDevice, LineList tempList, GameTime gameTime)
        {
            VertexPositionColor[] tempVertices;
            List<Color> colors = new List<Color>();
            colors.Add(Color.Red);
            colors.Add(Color.Yellow);
            colors.Add(Color.Green);
            colors.Add(Color.Blue);
            ColorScale colorScale = new ColorScale(colors);
          //  ColorMapper colorMapper = new ColorMapper(colorScale, _vectorfield.getMinPressure(), _vectorfield.getMaxPressure());
            ColorMapper colorMapper = new ColorMapper(colorScale, 0, 1800);

            foreach (List<Vector2> sLine in _lineVectors)
            {
                if (sLine.Count > 1)
                {
                    int i = 0;
                    tempVertices = new VertexPositionColor[sLine.Count];

                    foreach (Vector2 point in sLine)
                    {
                        if (i == sLine.Count)
                            break;
                        tempVertices[i].Position = new Vector3(point, 0f);
                        // add color according to pressure
                        tempVertices[i].Color = colorMapper.colorFor(_vectorfield.InterpolatePressureAt(point, true));
                        i++;
                    }
                    tempList.Vertices = tempVertices;
                    tempList.Draw(currentGraphicsDevice);
                }
            }


        }
    }
}
